package engine.asset
{
	import engine.core.*;
	import engine.loaders.*;
	import engine.profile.*;
	import flash.display3D.*;
	
	public class RxAsset
	{
		protected var m_type:int;
		protected var m_id:int;
		protected var m_url:String;
		protected var m_source:int;
		protected var m_name:String;
		protected var m_state:int;
		protected var m_loader:RxLoader;
		protected var m_loaderCallback:RxLoaderCallback;
		protected var m_size:int;
		protected var m_references:int;
		protected var m_suppressIOError:Boolean;
		protected var m_suppressDuplicateWarning:Boolean;
		protected var m_profiler:RxProfiler;
		protected var m_usedByGPU:Boolean;
		private var m_index:int;
		private var m_callbacks:Vector.<RxAssetCallback>;
		private var m_callbackClear:Boolean;
		private var m_semaphores:Vector.<RxSemaphore>;
		private static var s_numTypes:int;
		private static var s_typeNames:Vector.<String>;
		private static var s_createFunctions:Vector.<Function>;
		private static var s_assetArrays:Vector.<Vector.<RxAsset>>;
		private static var s_nameLookup:Vector.<Array>;
		private static var s_urlLookup:Vector.<Array>;
		private static var s_nextID:int;
		public static var s_loadRequestsImmediate:Boolean;
		public static var s_worker:RxTimerWorker;
		public static var s_context:Context3D;
		public static const STATE_EMPTY:int = 0;
		public static const STATE_LOADING:int = 1;
		public static const STATE_ERROR:int = 2;
		public static const STATE_READY:int = 3;
		public static const NUM_STATES:int = 4;
		public static const SOURCE_LOCAL:int = 0;
		public static const SOURCE_REMOTE:int = 1;
		
		public function RxAsset(type:int)
		{
			this.m_type = type;
			this.m_index = s_assetArrays[this.m_type].length;
			s_assetArrays[this.m_type].push(this);
			this.m_url = null;
			this.m_name = null;
			this.m_size = 0;
			this.m_state = RxAsset.STATE_EMPTY;
			this.m_source = RxAsset.SOURCE_LOCAL;
			this.m_loader = null;
			this.m_loaderCallback = null;
			this.m_callbacks = new Vector.<RxAssetCallback>;
			this.m_callbackClear = true;
			this.m_semaphores = new Vector.<RxSemaphore>;
			this.m_references = 1;
			this.m_suppressIOError = false;
			this.m_suppressDuplicateWarning = false;
			this.m_usedByGPU = false;
			this.m_profiler = null;
		}
		
		protected static function _getByName(value:String, type:int) : RxAsset
		{
			return s_nameLookup[type][value];
		}
		
		public static function Initialize(worker:RxTimerWorker) : void
		{
			s_typeNames = new Vector.<String>;
			s_createFunctions = new Vector.<Function>;
			s_assetArrays = new Vector.<Vector.<RxAsset>>;
			s_nameLookup = new Vector.<Array>;
			s_urlLookup = new Vector.<Array>;
			s_numTypes = 0;
			s_nextID = 1;
			s_loadRequestsImmediate = true;
			s_worker = worker;
			s_context = null;
			RegisterType("undefined", null);
		}
		
		public static function RegisterType(type:String, fun:Function) : int
		{
			type = type.toLowerCase();
			var name:* = s_typeNames.indexOf(type);
			if (name != -1)
			{
				return name;
			}
			
			// change for yzb
			var index:int = s_numTypes;
			s_typeNames[index] = type;
			s_createFunctions[index] = fun;
			s_assetArrays[index] = new Vector.<RxAsset>();
			s_nameLookup[index] = new Array();
			s_urlLookup[index] = new Array();
			
			s_numTypes++;
			return index;
		}
		
		public function SetName(name:String) : void
		{
			if (this.m_name != null)
			{
				RxLog.Warning("Setting a name on an asset that already has a name:" + name);
				return;
			}
			this.m_name = name;
			if (this.m_name == null)
			{
				return;
			}
			if (this.m_name == "")
			{
				return;
			}
			if (s_nameLookup[this.m_type][name] != null)
			{
				RxLog.Error("Asset must have a unique name : " + this.m_name);
			}
			else
			{
				s_nameLookup[this.m_type][name] = this;
			}
		}
		
		public function SetURL(url:String) : void
		{
			this.m_url = url;
			if (this.m_url == null || this.m_url == "")
			{
				return;
			}
			this.m_url = RxUtilities.NormalizeURL(this.m_url);
			var asset:* = s_urlLookup[this.m_type][this.m_url];
			if (asset != null)
			{
				if (this.m_suppressDuplicateWarning == false)
				{
					RxLog.Warning("Duplicate asset : " + this.m_url);
				}
				asset.push(this);
			}
			else
			{
				asset = new Vector.<RxAsset>;
				s_urlLookup[this.m_type][this.m_url] = asset;
				asset.push(this);
			}
		}
		
		public static function _getByURL(param1:String, param2:int) : RxAsset
		{
			param1 = RxUtilities.NormalizeURL(param1);
			var _loc_3:* = s_urlLookup[param2][param1];
			if (_loc_3 != null)
			{
				return _loc_3[0];
			}
			
			return null;
		}
		
		public function SetSource(param1:int) : void
		{
			this.m_source = param1;
		}
		
		public function AddCallback(param1:RxAssetCallback) : void
		{
			this.m_callbacks.push(param1);
		}
		
		public function Load() : void
		{
			this.m_id = s_nextID + 1;
		}
		
		protected function StartLoad(param1:String, param2:int, param3:Function) : RxLoader
		{
			var _loc_4:* = new RxLoader(param1, param2);
			_loc_4.SetSource(this.m_source);
			_loc_4.AddCompletionCallback(new RxLoaderCallback(param3));
			_loc_4.SuppressIOError(this.m_suppressIOError);
			if (s_loadRequestsImmediate)
			{
				_loc_4.Load();
			}
			else
			{
				this.m_loaderCallback = new RxLoaderCallback(this.LoadFunction);
				this.m_loaderCallback.m_loader = _loc_4;
				s_worker.AddTask(RxTimerWorker.PRIORITY_NORMAL, this.m_loaderCallback);
			}
			return _loc_4;
		}
		
		private function LoadFunction(param1:RxLoaderCallback) : Boolean
		{
			param1.m_loader.Load();
			param1.m_loader = null;
			
			return true;
		}
		
		protected function ExecuteCallbacks(param1:Boolean) : void
		{
			var _loc_2:RxAssetCallback = null;
			var _loc_3:RxSemaphore = null;
			for each (_loc_2 in this.m_callbacks)
			{
				
				_loc_2.m_result = param1;
				_loc_2.m_asset = this;
				_loc_2.m_function(_loc_2);
			}
			if (this.m_callbackClear == true && this.m_callbacks != null)
			{
				this.m_callbacks.length = 0;
			}
			if (this.m_semaphores != null)
			{
				for each (_loc_3 in this.m_semaphores)
				{
					
					_loc_3.Signal();
				}
				this.m_semaphores.length = 0;
			}
		}
		
		public function GetURL() : String
		{
			return this.m_url;
		}
		
		public static function GetCreateFromXMLFunction(param1:String) : Function
		{
			var _loc_2:* = s_typeNames.indexOf(param1.toLowerCase());
			if (_loc_2 != -1)
			{
				return s_createFunctions[_loc_2];
			}
			return null;
		}
		
		public function SuppressIOError() : void
		{
			this.m_suppressIOError = true;
		}
		
		public function Delete() : void
		{
			var _loc_2:RxAssetCallback = null;
			var _loc_3:RxSemaphore = null;
			var _loc_4:Vector.<RxAsset> = null;
			var _loc_5:int = 0;
			var _loc_6:int = 0;
			var _loc_1:* = s_assetArrays[this.m_type].pop();
			if (_loc_1 != this)
			{
				s_assetArrays[this.m_type][this.m_index] = _loc_1;
				_loc_1.m_index = this.m_index;
			}
			if (this.m_name != null)
			{
				delete s_nameLookup[this.m_type][this.m_name];
				this.m_name = null;
			}
			if (this.m_url != null)
			{
				_loc_4 = s_urlLookup[this.m_type][this.m_url];
				_loc_5 = _loc_4.length;
				_loc_6 = 0;
				while (_loc_6 < _loc_5)
				{
					
					if (_loc_4[_loc_6] == this)
					{
						_loc_1 = _loc_4.pop();
						if (_loc_1 != this)
						{
							_loc_4[_loc_6] = _loc_1;
						}
						if (_loc_4.length == 0)
						{
							delete s_urlLookup[this.m_type][this.m_url];
						}
						break;
					}
					_loc_6++;
				}
				this.m_url = null;
			}
			for each (_loc_2 in this.m_callbacks)
			{
				
				_loc_2.Delete();
			}
			this.m_callbacks.length = 0;
			this.m_callbacks = null;
			for each (_loc_3 in this.m_semaphores)
			{
				
				_loc_3.Delete();
			}
			this.m_semaphores.length = 0;
			this.m_semaphores = null;
			if (this.m_loader)
			{
				this.m_loader.Delete();
				this.m_loader = null;
			}
			if (this.m_loaderCallback)
			{
				s_worker.RemoveTask(this.m_loaderCallback, false);
				this.m_loaderCallback.m_loader = null;
				this.m_loaderCallback = null;
			}
			this.m_state = RxAsset.STATE_EMPTY;
			this.m_id = -this.m_id;
		}
		
		public function SetCallbackClear(param1:Boolean) : void
		{
			this.m_callbackClear = param1;
		}
		
		public static function LoadRequestsImmediate(param1:Boolean) : void
		{
			s_loadRequestsImmediate = param1;
		}
		
		public function SetUsedByGPU(param1:Boolean) : void
		{
			this.m_usedByGPU = param1;
		}
		
		public function SetProfiler(param1:RxProfiler) : void
		{
			this.m_profiler = param1;
		}
	}
}